package match

import (
	"sort"
)

type MatchPlayerList []*MatchPlayer
func (g MatchPlayerList) Len() int {
	return len(g)
}
func (g MatchPlayerList) Less(i, j int) bool {
	return g[i].Rating < g[j].Rating
}
func (g MatchPlayerList) Swap(i, j int) {
	g[i], g[j] = g[j], g[i]
}

// 匹配房间，把玩家按照一定的分段数分配到房间，原则上相同房间内的玩家是可以互相匹配的
// 匹配过程
// 		1 玩家加入匹配房间等待匹配组队
//		2 玩家加入等待队伍，直至该等待队伍满人
//		3 满人队伍进入最终匹配列表，匹配出足够的队伍，匹配成功
type MatchRoom struct {
	RoomId 		int32 	// 由积分分段得到的房间 id
	Players		[]*MatchPlayer 	// 等待组队的玩家列表
	WaitTeams	[]*MatchTeam 	// 正在组队的队伍列表，组完后进入 Teams
	Teams 		[]*MatchTeam 	// 已经组好的队伍，等待完成匹配
	IsDirty		bool

	Pool 		*MatchPool
}

func NewMatchRoom(roomId int32, pool *MatchPool) *MatchRoom {
	r := &MatchRoom{}
	r.RoomId = roomId
	r.IsDirty = false
	r.Pool = pool
	return r
}

func (r *MatchRoom) AddPlayer(p *MatchPlayer) {
	for _, v := range r.Players {
		if v == p {
			return
		}
	}
	r.Players = append(r.Players, p)
	r.IsDirty = true
}

func (r *MatchRoom) RemovePlayer(p *MatchPlayer) {
	for k, v := range r.Players {
		if v == p {
			r.IsDirty = true
			r.Players = append(r.Players[:k], r.Players[k+1:]...)
			break
		}
	}
}

func (r *MatchRoom) Sort() {
	if r.IsDirty {
		r.IsDirty = false
		sort.Sort(MatchPlayerList(r.Players))
	}
}

// 把等待中的玩家加入到等待匹配队伍
func (r *MatchRoom) MovePlayersToWaitTeam() {
	for i := 0; i < len(r.Players); i++ {
		if r.AddToTeam(r.Players[i]) {
			r.Players = append(r.Players[:i], r.Players[i+1:]...)
		} else {
			i++
		}
	}
}

func (r *MatchRoom) AddTeam(t *MatchTeam) {
	if t.IsEmpty() {
		return
	}
	if t.IsFull() {
		r.Teams = append(r.Teams, t)
	} else {
		r.WaitTeams = append(r.WaitTeams, t)
	}
}

func (r *MatchRoom) RemoveTeam(t *MatchTeam) {
	if t.IsFull() {
		for k, v := range r.Teams {
			if v == t {
				r.Teams = append(r.Teams[:k], r.Teams[k+1:]...)
				break
			}
		}
	} else {
		for k, v := range r.WaitTeams {
			if v == t {
				r.WaitTeams = append(r.WaitTeams[:k], r.WaitTeams[k+1:]...)
				break
			}
		}
	}
}

// 添加一个玩家到等待队伍
func (r *MatchRoom) AddToTeam(p *MatchPlayer) bool {
	if nil != p.Team {
		return false
	}
	for k, v := range r.WaitTeams {
		if v.AddPlayer(p) {
			if v.IsFull() {
				r.WaitTeams = append(r.WaitTeams[:k], r.WaitTeams[k+1:]...)
				r.Teams = append(r.Teams, v)
			}
			return true
		}
	}
	t := NewMatchTeam(r.Pool.TeamPlayerNum)
	t.AddPlayer(p)
	r.AddTeam(t)
	return true
}

// 把玩家从队伍中除出
func (r *MatchRoom) RemoveFromTeam(p *MatchPlayer) {
	if nil != p.Team {
		t := p.Team
		if t.IsFull() {
			t.RemovePlayer(p)
			for k, v := range r.Teams {
				if v == t {
					r.Teams = append(r.Teams[:k], r.Teams[k+1:]...)
					break
				}
			}
			if !t.IsEmpty() {
				r.WaitTeams = append(r.WaitTeams, t)
			}
		} else {
			t.RemovePlayer(p)
			if t.IsEmpty() {
				for k, v := range r.WaitTeams {
				if v == t {
					r.WaitTeams = append(r.WaitTeams[:k], r.WaitTeams[k+1:]...)
					break
				}
			}
			}
		}
	}
}

func (r *MatchRoom) MergeTeam(t *MatchTeam) {
	for _, v := range r.WaitTeams {
		if t != v && t.MergeTeam(v) && t.IsFull() {
			return
		}
	}
}

func (r *MatchRoom) OnDt(dt float64) {
	for _, v := range r.WaitTeams {
		v.Wait += dt
		// 太长时间没匹配到玩家，扩大匹配区间
		if v.RoomDis < r.Pool.MaxDis && int(v.Wait) > (int(v.RoomDis) + 1) * r.Pool.ExpandDt {
			v.RoomDis ++
		}
	}
	for _, v := range r.Teams {
		v.Wait += dt
		// 太长时间没匹配到玩家，扩大匹配区间
		if v.RoomDis < r.Pool.MaxDis && int(v.Wait) > (int(v.RoomDis) + 1) * r.Pool.ExpandDt {
			v.RoomDis ++
		}
	}
}
